#include "generation.h"

#include <iostream>

using std::cout;
using std::cin;
using std::stringstream;
using std::string;
using std::endl;

string itos(int i){
	stringstream ss;
	string s;
	ss << i;
	ss >> s;
	return s;
}
int stoi(const string& s){
	stringstream ss;
	int i;
	ss << s;
	ss >> i;
	return i;
}
string genname(int s, int l, int i){
	return "s_"+itos(s)+"_l_"+itos(l)+
			"("+itos(i)+")";
}
string gensignal(int s, int l, int i){
	return "signal s_"+itos(s)+"_l_"+itos(l) + 
			" : std_logic_vector("+itos(i-1)+" downto 0) := (others=>\'0\');";
}
bool generate(int size, int* cur, int* next, 
		stringstream& out, int layer){
	bool dowork = false;
	bool last = true;
	for(int i=0; i<size; ++i){
		if(cur[i]>3){
			last = false;
		}
		if(cur[i]>2){
			dowork = true;
		}
	}
	if(!dowork){
		return false;
	}
	
	out << endl << endl << "-- LAYER " << layer << " --" << endl << endl;
	
	for(int i=0; i<size-1; ++i){
		int j=0;
		while(j<cur[i]){
			string a, b, ci, s, co;
			if(cur[i]-j>=3){
				a=genname(i,layer,j);
				b=genname(i,layer,j+1);
				ci=genname(i,layer,j+2);
				s=genname(i,layer+1,next[i]++);
				co=genname(i+1,layer+1,next[i+1]++);
				genfulladder(a,b,ci,s,co,out);
				j+=3;
			} else if(cur[i]-j==2) {
				int test = next[i]%3;
				if(test==2 || (last && next[i]==1)){
					//half adder
					a=genname(i,layer,j);
					b=genname(i,layer,j+1);
					s=genname(i,layer+1,next[i]++);
					co=genname(i+1,layer+1,next[i+1]++);
					genhalfadder(a,b,s,co,out);
				} else {
					//connect directly
					a=genname(i,layer,j);
					b=genname(i,layer+1,next[i]++);
					out << b << " <= " << a << ";" << endl;
					a=genname(i,layer,j+1);
					b=genname(i,layer+1,next[i]++);
					out << b << " <= " << a << ";" << endl;
				}
				j+=2;
			} else if(cur[i]-j==1) {
				a=genname(i,layer,j);
				b=genname(i,layer+1,next[i]++);
				out << b << " <= " << a << ";" << endl;
				++j;
			}
		}
	}
	return true;
}

void genfulladder(const string& a, const string& b, const string& ci,
		const string& s, const string& co, stringstream& out){
	out << s << " <= " << a << " xor " << b << " xor " << ci << ";\n";
	out << co << " <= (" << a << " and " << b << ") or (" << b << " and " << ci
			<< ") or (" << a << " and " << ci << ");\n";
	
}

void genhalfadder(const string& a, const string& b, 
		const string& s, const string& co, stringstream& out){
	out << s << " <= " << a << " xor " << b << ";\n";
	out << co << " <= " << a << " and " << b << ";\n";
}

void genvhdltop(int i){
	cout << "library IEEE;" << endl;
	cout << "use IEEE.STD_LOGIC_1164.ALL;\n";
	cout << "use IEEE.STD_LOGIC_UNSIGNED.ALL;" << endl << endl;
	
	cout << "entity DADDA_" << i << " is\n";
	cout << "\tPort ( operand1 : in STD_LOGIC_VECTOR(" << i-1 << " downto 0);\n";
	cout << "\t\toperand2 : in STD_LOGIC_VECTOR(" << i-1 << " downto 0);\n";
	cout << "\t\tproduct : out STD_LOGIC_VECTOR(" << i+i-1 << " downto 0)\n";
	cout << "\t);\n";
	cout << "end DADDA_" << i << ";\n\n";
	
	cout << "architecture DADDA_" << i << "_arch of DADDA_" << i << " is\n";
	
	cout << "\n\nsignal and_result : std_logic_vector(" << i*i-1
			<< " downto 0) := (others=>'0');\n\n";
	cout << "signal part1, part2 : std_logic_vector(" << i+i-1
			<< " downto 0) := (others=>'0');\n\n";

}

void genvhdlend(int i){
	cout << "\n\nend DADDA_" << i << "_arch;\n\n";
}

void foo(){
	cout << "FOO was called!" << endl;
}

